昨天我們已經學會如何使用 Gin 以及 Gorm,並且在輸入網址 http://loaclhost:8080 可以看到 JSON 格式的 message,接下來,我們將要練習要怎麼 JSON 來傳送我要的資訊,以及建立資料及讀取資料。
在開始之前,大家可以先去看一下 Restful API
以及 如何使用 Postman
,之後的文章會用運用到這些知識點。
昨天已經有介紹過 Gorm
了,有了它我們就可以開始來做簡易貼文網站了,那他要怎麼運用在 Gin 裡面呢?
package main
import (
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// 建立一個 Post 結構體
type Post struct {
gorm.Model
Title string `json:"title"`
Content string `json:"content"`
}
func main() {
// 連接資料庫
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 自動遷移
db.AutoMigrate(&Post{})
// 建立第一筆 Post 資料
db.Create(&Post{Title: "學習使用 GORM", Content: "先安裝 GORM"})
r := gin.Default()
//找所有的貼文
var posts []Post
db.Find(&posts)
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"posts": posts,
})
})
// 啟動 Gin
r.Run()
}
第一步我們線連接到資料庫。第二步創建一個 Post 結構體。第三建立一個 Post 資料表。最後,建立一筆 Post 的資料。
完成後,執行該程式,並輸入 http://localhost:8080 ,我們就可以看到一筆 Post 的 JSON 資料,如下:
看到這樣的結果,就代表你成功建立了一筆資料,並且可以得到一筆資料。
我們稍微整理一下剛剛的程式碼,之後再做其他功能時也比較清楚這在做什麼,也比較好閱讀。
我們先建立等一下會用到的資料夾,分別是database
、model
、migration
,再來,在這三個資料夾內分別加上等等會用到的檔案,分別是database/db.go
、model/post_model.go
、migration/migrate.go
,整理完的檔案結構如下:
it-post
|-- database
| |-- db.go
|
|-- model
| |-- post_model.go
|
|-- migration
|-- migrate.go
我們先到 database/db.go
處理連接資料庫的東西:
// database/db.go
package database
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectToDB() {
// 連接 test 資料庫
var err error
DB, err = gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
}
這邊做了一點小更動,我們將 DB 設為全域變數,方便其他地方也方便使用。
我把 Post 這個結構體單獨放置,這樣在之後要看資料表的欄位是什麼也比較方便。
package model
import "gorm.io/gorm"
type Post struct {
gorm.Model
Title string `json:"title"`
Content string `json:"content"`
}
原先在 mian.go 的東西也要整理一下,將不必要的東西刪掉。
package main
import (
"it-post/config"
"it-post/model"
"github.com/gin-gonic/gin"
)
func main() {
database.ConnectToDB()
r := gin.Default()
// 查詢全部的 post
var posts []model.Post
database.DB.Find(&posts)
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"posts": posts,
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
這主要是要建立新的資料表所使用的檔案,所以他會稍稍不一樣:
package main
import (
"it-post/config"
"it-post/model"
)
func main() {
// 連接資料庫
database.ConnectToDB()
// 執行 Post 的遷移
err := config.DB.AutoMigrate(&model.Post{})
if err != nil {
panic("failed to migrate database")
}
}
那要怎麼使用呢?我們只要在終端機輸入 go run migration/migrate.go
,這樣就可以建立一個 Post
的資料表了。
C 代表著創建 (Create),其實在文章的一開始就已經有偷偷做了這件事,如下:
db.Create(&Post{Title: "學習使用 GORM", Content: "先安裝 GORM"})
這個意思就是在 Post 裡面增加一筆 Title
為 "學習使用 GORM" 以及 Content
為 "先安裝 GORM" 的資料,這個就是最簡單的創建資料的方式,那實際上要怎麼使用,我們到 main()
增加這一段,如下:
// 建立第一篇貼文
r.POST("/posts", func(c *gin.Context) {
var posts model.Post
if err := c.ShouldBindJSON(&posts); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Bad request data",
return
})
}
if err := database.DB.Create(&posts).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to create post",
return
})
}
c.JSON(http.StatusOK, gin.H{
"message": "Create post successfully",
})
})
程式碼解釋:
/posts
的路由,並使用 POST 請求。ShouldBindJSON
方法來解析 POST 請求中的 JSON 資料並存儲到 posts 變數中。如果發生解析錯誤,將會回傳 400 Bad Request 的錯誤訊息給客戶端。database.DB.Create(&posts)
進行儲存,如果發生了創建錯誤,將會回傳 500 Internal Server Error 的錯誤訊息給客戶端。打開 Postman,並且輸入 http://127.0.0.1:8080/posts ,接著,輸入你要傳的 JSON 資料,並 Send。
看到這個畫面就代表你成功建立了一則新貼文了。
接著,打開瀏覽器,並輸入 http://127.0.0.1:8080/ ,你會看到這樣的畫面:
為甚麼會有這些東西呢?接下來就要介紹CRUD的第二位角色。
R 代表著讀 (read),其實在一開始也偷偷做了這件事,如下:
var posts []model.Post
database.DB.Find(&posts)
這邊使用了 GORM 中的查找功能,這邊會找到所有的 Post 的資料,並且將其使用 JSON 傳遞出去。
但如果需要找特定資料的話,就需要用到不同的方法,一樣到 main() 增加這麼一段,如下:
r.GET("/posts/:id", func(c *gin.Context) {
id := c.Param("id")
var post model.Post
if err := database.DB.First(&post, id).Error; err != nil{
c.JSON(http.StatusInternalServerError, gin.H{
"error": "Failed to fetch posts",
})
return
}
c.JSON(http.StatusOK, gin.H{
"post": post,
})
})
程式碼解釋:
First(&post, id)
方法來從資料庫中根據提供的 id 查找並檢索相應的文章。如果出現錯誤,則返回一個內部服務器錯誤(500)的 JSON 回應。打開 Postman,並且輸入 http://127.0.0.1:8080/posts/1 ,接著,並 Send。
看到這個畫面就代表,你成功找到你要的貼文了。
如果是不存在的貼文呢?假設第三篇貼文,輸入 http://127.0.0.1:8080/posts/2:
如果找不到貼文,那就會回應 "Failed to fetch posts" 的 JSON 回應。
今天的內容很多,希望大家有看懂,同時我也把今天的內容更新到 Github上,明天將會介紹 CRUD 中剩下的兩個角色。我們明天見。